import Tablero
import HUnit
import Maybe

-- evaluar t para correr todos los tests
t = runTestTT allTests

allTests = test [
	"contenido" ~: testContenido,
	"poner" ~: testPoner,
	"generar" ~: testGenerar,
	"invertirTodas" ~: testInvertirTodas,
	"desplazar" ~: testDesplazar,
	"posicionesAInvertir" ~: testPosicionesAInvertir
	]

testContenido = test [
	_N ~=? fromJust (contenido d_4 tableroInicial),
	_N ~=? fromJust (contenido e_5 tableroInicial),
	_B ~=? fromJust (contenido e_4 tableroInicial),
	_B ~=? fromJust (contenido d_5 tableroInicial),
	True ~=? all isNothing [contenido pos tableroInicial | pos <- (todasLasPosMenos [d_4,e_5,e_4,d_5])]
	]
	
tablerosGeneradosInicial color = [poner pos color tableroInicial | pos <- (todasLasPosMenos [d_4,e_5,e_4,d_5])]

testPoner = test [
	--Agrego en cualquier lugar libre cualquier color y las posiciones iniciales no se modifican
	True ~=? all (\(Just color) -> color == _N) (map (contenido d_4) (tablerosGeneradosInicial _B)),
	True ~=? all (\(Just color) -> color == _N) (map (contenido d_4) (tablerosGeneradosInicial _N)),
	True ~=? all (\(Just color) -> color == _N) (map (contenido e_5) (tablerosGeneradosInicial _B)),
	True ~=? all (\(Just color) -> color == _N) (map (contenido e_5) (tablerosGeneradosInicial _N)),
	True ~=? all (\(Just color) -> color == _B) (map (contenido e_4) (tablerosGeneradosInicial _B)),
	True ~=? all (\(Just color) -> color == _B) (map (contenido e_4) (tablerosGeneradosInicial _N)),
	True ~=? all (\(Just color) -> color == _B) (map (contenido d_5) (tablerosGeneradosInicial _B)),
	True ~=? all (\(Just color) -> color == _B) (map (contenido d_5) (tablerosGeneradosInicial _N)),
	--Agrego y veo que el contenido de esa posicion es el color agregado
	True ~=? all (\(Just color) -> color == _B) ([contenido pos (poner pos _B tableroInicial) | pos <- posiciones]),
	True ~=? all (\(Just color) -> color == _N) ([contenido pos (poner pos _N tableroInicial) | pos <- posiciones]),
	--Agrego y veo que el resto del tablero (exceptuando posiciones iniciales y la recientemente agregada) esta vacio
	True ~=? all isNothing ([contenido posMenos (poner pos _B tableroInicial) | pos <- posiciones, posMenos <- todasLasPosMenos [d_4,e_5,e_4,d_5,pos] ]),
	True ~=? all isNothing ([contenido posMenos (poner pos _N tableroInicial) | pos <- posiciones, posMenos <- todasLasPosMenos [d_4,e_5,e_4,d_5,pos] ])
	]
	
testGenerar = test [
	--Recorro toda una columna desde las dos direcciones
	col_a ~~? generar a_1 (desplazarFila 1),
	col_a ~~? generar a_8 (desplazarFila (-1)),
	--Salto de a 7 para obtener las puntas
	col_puntas ~~? generar a_1 (desplazarFila 7),
	--Recorro toda una fila desde las dos direcciones
	fila_uno ~~? generar a_1 (desplazarColumna 1),	
	fila_uno ~~? generar h_1 (desplazarColumna (-1)),
	--Salto de a 7 para obtener las puntas
	fila_puntas ~~? generar a_1 (desplazarColumna 7)
	]
	
posInv pos color = (posicionesAInvertir pos (poner pos color tableroInicial))

testInvertirTodas = test [
	--Verifica que las fichas a invertir queden con el color correcto
	True ~=? all (\(Just color) -> color == _B) ([contenido posInvertidas (invertirTodas (posInv pos _B) (poner pos _B tableroInicial))| pos <- todasLasPosMenos [d_4,e_5,e_4,d_5], posInvertidas <- posInv pos _B]),
	True ~=? all (\(Just color) -> color == _N) ([contenido posInvertidas (invertirTodas (posInv pos _N) (poner pos _N tableroInicial))| pos <- todasLasPosMenos [d_4,e_5,e_4,d_5], posInvertidas <- posInv pos _N])
	]

testDesplazar = test [
	a_2 ~=? desplazarFila  1 a_1,
	a_1 ~=? desplazarFila (-1) a_2,
	b_1 ~=? desplazarColumna  1 a_1,
	a_1 ~=? desplazarColumna (-1) b_1
	]

testPosicionesAInvertir = test [
	[b_5,c_5,e_5,f_5,f_3,d_7,d_6,d_4,d_3,b_7,c_6,e_4,f_7,e_6,c_4,b_3] ~~? posicionesAInvertir d_5 tableroEstrella,
	[] ~=? posicionesAInvertir d_5 (poner d_5 _B (estrella d_5 _N 2))
	]

-- idem ~=? pero sin importar el orden
(~~?) :: (Ord a, Eq a, Show a) => [a] -> [a] -> Test
expected ~~? actual = (sort expected) ~=? (sort actual)
	where
		sort = foldl (\r e -> push r e) []
		push r e = (filter (e<=) r) ++ [e] ++ (filter (e>) r)

(~~) :: (Ord a, Eq a, Show a) => [a] -> [a] -> Bool
expected ~~ actual = (sort expected) == (sort actual)
	where
		sort = foldl (\r e -> push r e) []
		push r e = (filter (e<=) r) ++ [e] ++ (filter (e>) r)

-- constantes para que los tests sean más legibles		
_N = Negro	
_B = Blanco
a_1 = ('a',1::Int)
b_1 = ('b',1::Int)
c_1 = ('c',1::Int)
d_1 = ('d',1::Int)
e_1 = ('e',1::Int)
f_1 = ('f',1::Int)
g_1 = ('g',1::Int)
h_1 = ('h',1::Int)

a_2 = ('a',2::Int)
b_2 = ('b',2::Int)
c_2 = ('c',2::Int)
d_2 = ('d',2::Int)
e_2 = ('e',2::Int)
f_2 = ('f',2::Int)
g_2 = ('g',2::Int)
h_2 = ('h',2::Int)

a_3 = ('a',3::Int)
b_3 = ('b',3::Int)
c_3 = ('c',3::Int)
d_3 = ('d',3::Int)
e_3 = ('e',3::Int)
f_3 = ('f',3::Int)
g_3 = ('g',3::Int)
h_3 = ('h',3::Int)

a_4 = ('a',4::Int)
b_4 = ('b',4::Int)
c_4 = ('c',4::Int)
d_4 = ('d',4::Int)
e_4 = ('e',4::Int)
f_4 = ('f',4::Int)
g_4 = ('g',4::Int)
h_4 = ('h',4::Int)

a_5 = ('a',5::Int)
b_5 = ('b',5::Int)
c_5 = ('c',5::Int)
d_5 = ('d',5::Int)
e_5 = ('e',5::Int)
f_5 = ('f',5::Int)
g_5 = ('g',5::Int)
h_5 = ('h',5::Int)

a_6 = ('a',6::Int)
b_6 = ('b',6::Int)
c_6 = ('c',6::Int)
d_6 = ('d',6::Int)
e_6 = ('e',6::Int)
f_6 = ('f',6::Int)
g_6 = ('g',6::Int)
h_6 = ('h',6::Int)

a_7 = ('a',7::Int)
b_7 = ('b',7::Int)
c_7 = ('c',7::Int)
d_7 = ('d',7::Int)
e_7 = ('e',7::Int)
f_7 = ('f',7::Int)
g_7 = ('g',7::Int)
h_7 = ('h',7::Int)

a_8 = ('a',8::Int)
b_8 = ('b',8::Int)
c_8 = ('c',8::Int)
d_8 = ('d',8::Int)
e_8 = ('e',8::Int)
f_8 = ('f',8::Int)
g_8 = ('g',8::Int)
h_8 = ('h',8::Int)

posIniciales = [d_4,e_5,e_4,d_5]
posiciones = [ (x,y::Int) | x<-['a'..'h'], y<-[1..8] ]

col_a = [ ('a',y::Int) | y<-[1..8] ]
col_puntas = [('a',1::Int),('a',8::Int)]
fila_uno =  [ (x,1::Int) | x<-['a'..'h'] ]
fila_puntas = [('a',1::Int),('h',1::Int)]

todasLasPosMenos poss = (filter (not.(flip elem poss)) posiciones)

estrella centro color tam = foldr (\d t -> rodear centro color d t) vacio [1..tam]
tableroEstrella = poner d_5 _B (rodear d_5 _B 3 (estrella d_5 _N 2))
rodear centro color distancia tablero = foldr (\p t -> poner p color t) tablero posiciones
	where posiciones = map (\f -> f centro) [ desp c | desp <- [desplazarFila,desplazarColumna,desplazarDiagonalA,desplazarDiagonalB], c <- [-distancia, distancia] ]

